const sm2 = require('sm-crypto').sm2
const dh_track = {
    // 用户生成唯一字符串的字符集
    charsStr: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
    // sdk版本
    sdkVersion: '1.0.0',
    // 浏览器用户代理端
    ua: navigator.userAgent,
    // 应用生命周期id，贯穿本次系统加载
    sessionId: '',
    // imei 的长度
    imeiLen: 17,
    // 仅需获取一次的参数集合
    onceParams: ['imei', 'resolution', 'domain', 'sdkVersion'],
    // 需多次获取的参数集合
    repeatParams: ['localTime', 'title', 'referrer', 'url', 'sh', 'sw', 'logId'],
    // 待上报的公共参数，全埋点上报数据
    pubParams: {
        eventName: '', // 事件名称
        uid: '', //用户id，用户唯一标识，登录前置空，登录后可通过函数setParam 设置为账号（手机号、邮箱等）
        imei: '', //设备唯一标识 长度17 只获取一次
        localTime: '', //触发时的本地时间，时间戳
        domain: '', //document.domain
        url: '', // location.url
        title: '', //页面标题
        referrer: '', //document.referrer
        sh: 0, //屏幕高度
        sw: 0, //屏幕宽度
        resolution: '', //分辨率
        logId: '', //当前日志的id，唯一性
    },
    // page的数据
    pageParams: {
        title: '', //页面标题
        // url : location.url,  //页面地址
        referrer: document.referrer,
        duringTime: 0,
        pageId: '' //页面id
    },
    // 基础配置
    baseConfig: {
        serveUrl: '', //上报地址
        switch: true, // 是否开启上报
        debugger: false, // 是否开启调试模式，默认关闭，开启后控制台会打印调试信息
        publicKey: '', // 加密密钥
        privateKey: '',
        click: false, //是否开启监听所有点击事件
        handleFail: false, //是否开启失败重新上报
    },
    // 页面生命周期&劫持事件
    pageEvent: {
        DOMContentLoaded() {
            // 当前事件需要单独上报的参数
            const params = {};
            dh_track._sendDataToServer(dh_track._parseParam(params));
        },
        load() {
            dh_track._sendDataToServer(dh_track._parseParam({}));
        },
        beforeunload() {
            dh_track._sendDataToServer(dh_track._parseParam({}));
        },
        unload() {
            dh_track._sendDataToServer(dh_track._parseParam({}));
        },
        // 如无特殊需求（网页点击热力图等），此事件慎用
        click(e) {
            if (!dh_track.baseConfig.click) return;
            dh_track._sendDataToServer(dh_track._parseParam({
                eventType: 'click',
                clientX: e.clientX || 0, //点击位置距离当前body可视区域的x坐标
                clientY: e.clientY || 0, //点击位置距离当前body可视区域的y坐标
                url: location.href
            }));
        },
    },
    // 获取参数方法集合
    getParamFnc: {
        // sdk版本
        sdkVersion() {
            dh_track.pubParams.sdkVersion = dh_track.sdkVersion;
        },
        logId() {
            dh_track.getParamFnc.imei();
            dh_track.pubParams.logId = dh_track.pubParams.imei + '_' + new Date().getTime()
        },
        // 生成imei
        imei() {
            var _imei = localStorage.getItem('dh_track_imei');
            if (_imei) {
                dh_track.pubParams.imei = _imei;
            } else {
                // 初始化sdk时随机生成一个尽可能唯一性且永久存储在本地的字符串
                _imei = '';
                const _charsArr = dh_track.charsStr.split('');
                const _len = _charsArr.length;
                const _imeiLen = dh_track.imeiLen;
                for (let i = 0; i < _imeiLen; i++) {
                    let _char = _charsArr[Math.floor(Math.random() * _len)];
                    _imei += _char;
                }
                dh_track.pubParams.imei = _imei;
                localStorage.setItem('dh_track_imei', _imei);
            }
        },
        // 获取网络状态
        net() {
            let _net = '';
            try {
                if (navigator.connection.effectiveType) {
                    _net = navigator.connection.effectiveType;
                }
                dh_track.pubParams.net = _net;
            } catch (err) {
                console.log('获取网络状态报错:', err);
            }
        },
        // 事件触发时的本地时间，每次调用时获取
        localTime() {
            dh_track.pubParams.localTime = new Date().getTime();
        },
        url() {
            dh_track.pubParams.url = location.href;
        },
        title() {
            dh_track.pubParams.title = document.title || '';
        },
        // 此方法对于单页面系统无效，因为 referrer 只在页面跳转情况下才能获取到真实数据，比如超链接跳转、location.href赋值等
        referrer() {
            dh_track.pubParams.referrer = document.referrer || '';
        },
        // 浏览器
        browser() {
            dh_track.pubParams.browser = dh_track.methods.getBrowser();
        },
        // 操作系统
        os() {
            dh_track.pubParams.os = dh_track.methods.getOs();
        },
        // 浏览器版本
        browser_version() {
            dh_track.pubParams.browser_version = dh_track.methods.getBrowserVersion();
        },
        domain() {
            dh_track.pubParams.domain = document.domain || '';
        },
        // 系统分辨率
        resolution() {
            dh_track.pubParams.resolution = dh_track.methods.getResolution();
        },
        // 屏幕高度
        sh() {
            dh_track.pubParams.sh = window.screen.height || 0;
        },
        // 屏幕宽度
        sw() {
            dh_track.pubParams.sw = window.screen.width || 0;
        },

    },
    // 方法集合
    methods: {
        // 获取浏览器类型
        getBrowser() {
            var u = dh_track.ua;
            var bws = [{
                name: 'sgssapp',
                it: /sogousearch/i.test(u)
            }, {
                name: 'wechat',
                it: /MicroMessenger/i.test(u)
            }, {
                name: 'weibo',
                it: !!u.match(/Weibo/i)
            }, {
                name: 'uc',
                it: !!u.match(/UCBrowser/i) || u.indexOf(' UBrowser') > -1
            }, {
                name: 'sogou',
                it: u.indexOf('MetaSr') > -1 || u.indexOf('Sogou') > -1
            }, {
                name: 'xiaomi',
                it: u.indexOf('MiuiBrowser') > -1
            }, {
                name: 'baidu',
                it: u.indexOf('Baidu') > -1 || u.indexOf('BIDUBrowser') > -1
            }, {
                name: '360',
                it: u.indexOf('360EE') > -1 || u.indexOf('360SE') > -1
            }, {
                name: '2345',
                it: u.indexOf('2345Explorer') > -1
            }, {
                name: 'edge',
                it: u.indexOf('Edge') > -1
            }, {
                name: 'ie11',
                it: u.indexOf('Trident') > -1 && u.indexOf('rv:11.0') > -1
            }, {
                name: 'ie',
                it: u.indexOf('compatible') > -1 && u.indexOf('MSIE') > -1
            }, {
                name: 'firefox',
                it: u.indexOf('Firefox') > -1
            }, {
                name: 'safari',
                it: u.indexOf('Safari') > -1 && u.indexOf('Chrome') === -1
            }, {
                name: 'qqbrowser',
                it: u.indexOf('MQQBrowser') > -1 && u.indexOf(' QQ') === -1
            }, {
                name: 'qq',
                it: u.indexOf('QQ') > -1
            }, {
                name: 'chrome',
                it: u.indexOf('Chrome') > -1 || u.indexOf('CriOS') > -1
            }, {
                name: 'opera',
                it: u.indexOf('Opera') > -1 || u.indexOf('OPR') > -1
            }]
            for (var i = 0; i < bws.length; i++) {
                if (bws[i].it) {
                    return bws[i].name
                }
            }
            return 'other'
        },
        // 获取操作系统
        getOs() {
            var u = dh_track.ua;
            if (!!u.match(/compatible/i) || u.match(/Windows/i)) {
                return 'windows'
            } else if (!!u.match(/Macintosh/i) || u.match(/MacIntel/i)) {
                return 'macOS'
            } else if (!!u.match(/iphone/i) || u.match(/Ipad/i)) {
                return 'ios'
            } else if (u.match(/android/i)) {
                return 'android'
            } else if (u.match(/Ubuntu/i)) {
                return 'Ubuntu'
            } else {
                return 'other'
            }
        },
        // 获取浏览器版本
        getBrowserVersion() {
            var Sys = {};
            var ua = dh_track.ua.toLowerCase();
            var s;
            (s = ua.match(/rv:([\d.]+)\) like gecko/)) ? Sys.ie = s[1]:
                (s = ua.match(/msie ([\d\.]+)/)) ? Sys.ie = s[1] :
                (s = ua.match(/edge\/([\d\.]+)/)) ? Sys.edge = s[1] :
                (s = ua.match(/firefox\/([\d\.]+)/)) ? Sys.firefox = s[1] :
                (s = ua.match(/(?:opera|opr).([\d\.]+)/)) ? Sys.opera = s[1] :
                (s = ua.match(/chrome\/([\d\.]+)/)) ? Sys.chrome = s[1] :
                (s = ua.match(/version\/([\d\.]+).*safari/)) ? Sys.safari = s[1] : 0;
            // 根据关系进行判断
            if (Sys.ie) return (Sys.ie);
            if (Sys.edge) return (Sys.edge);
            if (Sys.firefox) return (Sys.firefox);
            if (Sys.chrome) return (Sys.chrome);
            if (Sys.opera) return (Sys.opera);
            if (Sys.safari) return (Sys.safari);
            return '';
        },
        // 获取分辨率
        getResolution() {
            const ratio = window.devicePixelRatio || 1;
            return (Math.min(screen.width, screen.height) * ratio) +
                'x' + (Math.max(screen.width, screen.height) * ratio);
        },
    },
    /**
     * 数据上报
     * @param { String } data 
     */
    _sendDataToServer(data) {
        const iimg = new Image(1, 1);
        iimg.onerror = function() {
            // 失败重试
            dh_track.baseConfig.handleFail && dh_track._sendDataToServer(data);
        };
        iimg.src = this.baseConfig.serveUrl + '/log.gif?logType=web&log=' + data;
    },
    /**
     * 参数编码返回字符串，拼接所有参数
     * @param {*} param
     * @returns 
     */
    _parseParam(param) {
        // 公共参数拼接
        const data = Object.assign({ sid: this.sessionId }, this.pubParams, {
            page: JSON.stringify(this.pageParams)
        }, param);
        dh_track.baseConfig.debugger && console.log('加密前的数据：', JSON.stringify(data));
        const encryptData = sm2.doEncrypt(JSON.stringify(data), dh_track.baseConfig.publicKey, 0);
        dh_track.baseConfig.debugger && console.log('加密后的数据：', encryptData);
        // 解密数据
        let decryptData = sm2.doDecrypt(encryptData, dh_track.baseConfig.privateKey, 0)
        dh_track.baseConfig.debugger && console.log('解密后的数据：', decryptData);
        return encryptData;
    },
    // 仅需要一次性获取的参数，比如设备品牌、浏览器等
    _getOnceParams() {
        let arr = this.onceParams;
        for (let i = 0; i < arr.length; i++) {
            if (typeof dh_track.getParamFnc[arr[i]] === 'function') {
                dh_track.getParamFnc[arr[i]]();
            }
        }
    },
    // 每次上报重新获取的参数赋值
    _getRepeatParams() {
        let arr = this.repeatParams;
        for (let i = 0; i < arr.length; i++) {
            if (typeof dh_track.getParamFnc[arr[i]] === 'function') {
                dh_track.getParamFnc[arr[i]]();
            }
        }
    },
    /**
     * 
     * 获取page_id
     * @returns 
     */
    _getPageId() {
        try {
            var arr = location.href.split(location.host);
            return arr[arr.length - 1];
        } catch (err) {
            console.log(err);
        }
    },
    /**
     * 设置特定或者自定义参数，比如登录之后需要把 uid 重置为手机号、邮箱等，或者上传一个自定义参数，支持链式编程
     * @param { Object } params 
     */
    setParam(params) {
        for (let key in params) {
            if (key && params[key]) {
                this.pubParams[key] = params[key];
            }
        }
        return this;
    },
    /**
     * 事件上报
     * @param { String } eventName 事件名称
     * @param { Object }} params 事件属性对象
     */
    trackEvent(eventName, params) {
        if (!dh_track.baseConfig.switch) return
            // 需要重复获取的字段
        dh_track._getRepeatParams();
        let keysArr = [];
        let paramsStr = '';
        dh_track.pubParams.eventName = eventName;
        params.eventName = eventName;
        // 发送pv事件
        dh_track.setPageParam(params);
        if (params) {
            keysArr = Object.keys(params);
            if (keysArr.length > 0) {
                // let str = encodeURIComponent(JSON.stringify(params));
                paramsStr = JSON.stringify(params);
            }
        }
        dh_track._sendDataToServer(dh_track._parseParam({
            actions: paramsStr
        }));
    },
    // 设置 page 中的字段
    setPageParam(params) {
        let o = {
            title: document.title, //页面标题
            // url : location.href,  //页面地址
            referrer: document.referrer,
            duringTime: 0,
            pageId: '',
            url: ''
        };
        if (params && params.during_time) {
            o.duringTime = params.duringTime;
        }
        dh_track.pageParams = o;
    },
    // 初始化配置事件，支持链式编程
    init(params) {
        // 设置基础配置，初始化sdk时传入
        for (let key in params) this.baseConfig[key] = params[key];
        // 设置公共参数，只在初始化sdk时获取一次，以后不再获取
        this._getOnceParams();
        // 绑定页面周期&劫持事件
        // Object.keys(this.pageEvent).forEach(hook => {
        //     // 需要重复获取的字段
        //     dh_track._getRepeatParams();
        //     dh_track.setPageParam();
        //     console.log(dh_track.pageParams);
        //     window.addEventListener(hook, this.pageEvent[hook]);
        // })
        return this;
    },
};
export default dh_track;